package com.sws.worktive.volley;

import java.io.UnsupportedEncodingException;

import android.content.Context;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

/**
 * GsonRequest adds Request<T> to VolleyRequestQueue <br/>
 * Also handles the Json Response returned from Service <br/> 
 * and converts to POJO class
 * @author MB
 * @param <T>
 *            POJO class as Type Parameter <br/>
 */
public class GsonRequest<T> extends Request<T>{

	/** Charset for request. */
    private static final String PROTOCOL_CHARSET = "utf-8";
    
    /** Content type for request. */
    private static final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", PROTOCOL_CHARSET);
    
	private Listener<T> responseListener = null;
	private String requestBody = null;
	private Gson gson = new Gson();
	private Class<T> handlerClass = null;
	private Context applicationContext;
		
	/**
	 * Constructor for initializing Request
	 * @param method GET or POST
	 * @param url 
	 * @param requestBody null for GET method / String payload for POST method
	 * @param responseListener Response success listener
	 * @param errorListener Response error listener
	 * @param handlerClass ResponseParserClass
	 * @param applicationContext context
	 */
	public GsonRequest(int method, String url, String requestBody, Listener<T> responseListener, ErrorListener errorListener, Class<T> handlerClass, Context applicationContext){
		super(method, url, errorListener);
		this.responseListener = responseListener;
		this.requestBody = requestBody;
		this.handlerClass = handlerClass;
		this.applicationContext = applicationContext;
	}

	/**
	 * Parse the response using Gson and return to DeliverResponse as Object of Response Parser Class
	 */
	@Override
	protected Response<T> parseNetworkResponse(NetworkResponse response) {
		try {
			String json = new String(response.data,
					HttpHeaderParser.parseCharset(response.headers));
			return Response.success(gson.fromJson(json, handlerClass),
					HttpHeaderParser.parseCacheHeaders(response));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
        	e.printStackTrace();
            return Response.error(new ParseError(e));
        }	
	}

	/**
	 * Delivers the Response as an object of the Parser Class
	 */
	@Override
	protected void deliverResponse(T response) {
		responseListener.onResponse(response);
	}

	/**
	 * Set ConnectionTimeOut, RetryCount, BackoffMultiplierForRetryConnection
	 */
	@Override
	public Request<?> setRetryPolicy(RetryPolicy retryPolicy) {
		return super.setRetryPolicy(retryPolicy);
	}

	@Override
	@Deprecated
	public String getPostBodyContentType() {
		return getBodyContentType();
	}
	
	/**
	 * Adds RequestProperty("Content-Type", "application/json; charset=utf-8")
	 * to the HttpUrlConnection for JsonHeader
	 * (Refer addBodyIfExists(HttpUrlConnection, Request) in HurlStack in Volley
	 */
	@Override
	public String getBodyContentType() {
		return PROTOCOL_CONTENT_TYPE;
	}

	@Override
	@Deprecated
	public byte[] getPostBody() throws AuthFailureError {
		return getBody();
	}

	/**
	 * Adds the Body (PayLoad) to the HttpUrlConnection
	 * (Refer addBodyIfExists(HttpUrlConnection, Request) in HurlStack in Volley
	 */
	@Override
	public byte[] getBody() throws AuthFailureError {
		try {
            return requestBody == null ? null : requestBody.getBytes(PROTOCOL_CHARSET);
        } catch (UnsupportedEncodingException uee) {
            VolleyLog.e("Unsupported Encoding while trying to get the bytes of %s using %s",
            		requestBody, PROTOCOL_CHARSET);
            return null;
        }
	}

	public void execute() {
		MyVolley.getMyVolley(applicationContext).addToRequestQueue(this);
	}
	
	public void execute(String tag) {
		MyVolley.getMyVolley(applicationContext).addToRequestQueue(this, tag);
	}
}
